package dom.xpath.data;

import dom.xpath.util.Token;
import dom.xpath.util.TokenList;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;

/**
 * This class allows to output XML results via SAX.
 *
 * @author Workgroup DBIS, University of Konstanz 2005-07, ISC License
 * @author Christian Gruen
 */
public final class ResultReader implements XMLReader {
  /** Content handler reference. */
  private ContentHandler handler;
  /** Query result. */
  private final Result result;

  /**
   * Constructor.
   * @param res query result
   */
  public ResultReader(final Result res) {
    result = res;
  }

  /* Implements XMLReader method. */
  public ContentHandler getContentHandler() {
    return handler;
  }

  /* Implements XMLReader method. */
  public DTDHandler getDTDHandler() {
    return null;
  }

  /* Implements XMLReader method. */
  public EntityResolver getEntityResolver() {
    return null;
  }

  /* Implements XMLReader method. */
  public ErrorHandler getErrorHandler() {
    return null;
  }

  /* Implements XMLReader method. */
  public boolean getFeature(final String name) {
    return false;
  }

  /* Implements XMLReader method. */
  public Object getProperty(final String name) {
    return null;
  }

  /* Implements XMLReader method. */
  public void parse(final InputSource input) throws SAXException {
    // execute query
    handler.startDocument();
    result.serialize(this);
    handler.endDocument();
  }

  /* Implements XMLReader method. */
  public void parse(final String id) throws SAXException {
    // execute query
    handler.startDocument();
    result.serialize(this);
    handler.endDocument();
  }

  /* Implements XMLReader method. */
  public void setContentHandler(final ContentHandler h) {
    handler = h;
  }

  /* Implements XMLReader method. */
  public void setDTDHandler(final DTDHandler h) {
    throw new RuntimeException("Not supported yet.");
  }

  /* Implements XMLReader method. */
  public void setEntityResolver(final EntityResolver resolver) {
    throw new RuntimeException("Not supported yet.");
  }

  /* Implements XMLReader method. */
  public void setErrorHandler(final ErrorHandler h) {
    throw new RuntimeException("Not supported yet.");
  }

  /* Implements XMLReader method. */
  public void setFeature(final String name, final boolean value) {
    throw new RuntimeException("Not supported yet.");
  }

  /* Implements XMLReader method. */
  public void setProperty(final String name, final Object value)
      throws SAXNotSupportedException {
    throw new SAXNotSupportedException("Not supported yet.");
  }

  /**
   * Sends a startElement event to the content handler.
   * @param t tag
   * @throws SAXException SAX exception
   */
  public void startElement(final String t) throws SAXException {
    handler.startElement("", "", t, new AttributesImpl());
  }

  /**
   * Sends a startElement event to the content handler.
   * @param t tag
   * @param a attributes
   * @throws SAXException SAX exception
   */
  public void startElement(final String t, final TokenList a)
      throws SAXException {
    final AttributesImpl atts = new AttributesImpl();
    for(int i = 0; i < a.size; i += 2) {
      atts.addAttribute("", "", Token.string(a.list[i]), "",
          Token.string(a.list[i + 1]));
    }
    handler.startElement("", "", t, atts);
  }

  /**
   * Sends an endElement event to the content handler.
   * @param t tag
   * @throws SAXException SAX exception
   */
  public void endElement(final String t) throws SAXException {
    handler.endElement("", "", t);
  }

  /**
   * Sends a processingInstruction event to the content handler.
   * @param n name
   * @param v value
   * @throws SAXException SAX exception
   */
  public void pi(final byte[] n, final byte[] v) throws SAXException {
    handler.processingInstruction(Token.string(n), Token.string(v));
  }

  /**
   * Sends a characters event to the content handler.
   * @param b text bytes
   * @throws SAXException SAX exception
   */
  public void text(final byte[] b) throws SAXException {
    final char[] c = Token.string(b).toCharArray();
    handler.characters(c, 0, c.length);
  }
}
